using System.Collections.Generic;
using System.Linq;
using JetBrains.ReSharper.Feature.Services.CSharp.Generate;
using JetBrains.ReSharper.Feature.Services.Generate;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.CSharp;
using JetBrains.ReSharper.Psi.Util;
using MugenMvvmToolkit.ReSharper.Infrastructure;

namespace MugenMvvmToolkit.ReSharper.ViewModels.Generators
{
    [GeneratorBuilder(GeneratorKindConstants.GenerateModelProperties, typeof(CSharpLanguage))]
    public class ModelPropertiesGeneratorBuilder : GeneratorBuilderBase<CSharpGeneratorContext>
    {
        #region Nested types

        private struct Options
        {
            #region Fields

            public const string ImplementPropertyChangedNotificationKey = "ImplementPropertyChangedNotificationKey";
            public const string WrapInRegionKey = "WrapInRegionKey";
            private readonly CSharpGeneratorContext _context;

            #endregion

            #region Constructors

            /// <summary>
            ///     Initializes a new instance of the <see cref="T:System.Object" /> class.
            /// </summary>
            public Options(CSharpGeneratorContext context)
                : this()
            {
                _context = context;
            }

            #endregion

            #region Properties

            public bool WrapInRegion
            {
                get { return bool.Parse(_context.GetGlobalOptionValue(WrapInRegionKey)); }
            }

            public bool ImplementPropertyChangedNotification
            {
                get { return bool.Parse(_context.GetGlobalOptionValue(ImplementPropertyChangedNotificationKey)); }
            }

            #endregion
        }

        #endregion

        #region Overrides of GeneratorBuilderBase<CSharpGeneratorContext>

        public override double Priority
        {
            get { return 0; }
        }

        protected override void Process(CSharpGeneratorContext context)
        {
            IType modelType = ToolkitExtensions.GetEntityModelType(context.ClassDeclaration);
            if (modelType == null)
                return;
            IClass modelClass = modelType.GetClassType();
            if (modelClass == null)
                return;

            var selectedItems = context.InputElements
                .OfType<GeneratorDeclaredElement>()
                .Select(element => element.DeclaredElement)
                .OfType<IProperty>();
            var options = new Options(context);
            var elementFactory = CSharpElementFactory.GetInstance(context.PsiModule);
            new ModelPropertyGenerator(context.ClassDeclaration, modelClass, elementFactory)
                .Generate(options.ImplementPropertyChangedNotification, options.WrapInRegion, selectedItems);
        }

        protected override IList<IGeneratorOption> GetGlobalOptions(CSharpGeneratorContext context)
        {
            return new List<IGeneratorOption>
            {
                new GeneratorOptionBoolean(Options.ImplementPropertyChangedNotificationKey,
                    UiResources.ImplementPropertyChangedNotification, true) {Persist = true},
                new GeneratorOptionBoolean(Options.WrapInRegionKey, UiResources.WrapInRegion, false) {Persist = true},
            };
        }

        #endregion
    }
}